package com.communal.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.servlet.ServletContext;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.communal.dao.IModelDao;
import com.communal.service.IApplicationService;
import com.communal.util.AppContextConfig;
import com.communal.util.AppException;

/**
 * Implements common application operations
 * @author Created by andrey.kuznetsov <br>
 * @author Last modified by $Author$ <br>
 * @author Last modified on $Date$ at revision $Revision$ <br>
 */

@Service
public class ApplicationService extends AbstractService implements IApplicationService {
	
	private final String VERSIONS_FILE_PATH = "/WEB-INF/versions.xml";
	
	private final String NEW_LINE_CHAR = "\n";
	
	private final String XML_KEY_CURRENT_VERSION = "current_version";
	private final String XML_KEY_VERSIONS = "versions";
	private final String XML_KEY_VERSION = "version";
	private final String XML_KEY_FEATURE = "feature";
	private final String XML_KEY_VALUE = "value";
	
	@Autowired
	IModelDao modelDao;
	
	@Override
	public String getApplicationAboutData() throws AppException {
		StringBuffer applicationInfoText = new StringBuffer();
		try{
			applicationInfoText.append(messageSource.getMessage("application.info.program", null, null));
			applicationInfoText.append(messageSource.getMessage("application.info.title", null, null));
			applicationInfoText.append(getApplicationInfo(AppContextConfig.getServletContext()));
		}catch (Exception err) {
			throw new AppException(messageSource.getMessage("message.error.common", null, null));
		}	
		return applicationInfoText.toString();
	}

	/**
	 * Parses xml file with application information and build string for response <br>
	 * @param p_servletContext servlet context; {@link String} <br>
	 * @return string which contains detail information about application versions <br>
	 * @throws JDOMException - if exception happens while parsing xml file
	 * @throws IOException - if exception happens on IO level
	 */
    @SuppressWarnings("unchecked")
	private String getApplicationInfo(ServletContext p_servletContext) throws JDOMException, IOException{
    	
    	StringBuffer versionStr = new StringBuffer();
 
    	InputStream inputStream = p_servletContext.getResourceAsStream(VERSIONS_FILE_PATH);
        SAXBuilder builder = new SAXBuilder();
        Document document = builder.build(inputStream);
   
        Element rootElement = document.getRootElement();
        	
        if(rootElement != null){
        		
        	Element currentVersionElement = rootElement.getChild(XML_KEY_CURRENT_VERSION);
        	if(currentVersionElement != null){
        		String currentVersion = currentVersionElement.getAttributeValue(XML_KEY_VALUE);
        		if(StringUtils.isNotEmpty(currentVersion)){
        			versionStr.append(messageSource.getMessage("application.info.version", new Object[]{currentVersion}, null))
        			.append(NEW_LINE_CHAR)
        			.append(NEW_LINE_CHAR);
        		}
        	}
        		
        	Element versionsElement = rootElement.getChild(XML_KEY_VERSIONS);
        	if(versionsElement != null){
        		List<Element> versionElementList = versionsElement.getChildren(XML_KEY_VERSION);
        		if(CollectionUtils.isNotEmpty(versionElementList)){
        			StringBuffer featureStrBuffer = new StringBuffer();
        			String versionNumber = null;
        			List<Element> featureElementList = null;
        			for(Element versionElement : versionElementList){
        				versionNumber = versionElement.getAttributeValue(XML_KEY_VALUE);
        				featureElementList = versionElement.getChildren(XML_KEY_FEATURE);
        				if(CollectionUtils.isNotEmpty(featureElementList)){
        					featureStrBuffer = new StringBuffer();
        					for(Element featureElement: featureElementList){
        						featureStrBuffer.append(featureElement.getAttributeValue(XML_KEY_VALUE)).append(NEW_LINE_CHAR);
        					}
        				}
        					
        				if(StringUtils.isNotEmpty(versionNumber)){
        					versionStr.append(messageSource.getMessage("application.info.version.history", 
        						new Object[]{versionNumber, featureStrBuffer.toString()}, null));
        				}
        			}
        		}
        	}
        }
    	return versionStr.toString();
    }
}
